import Axios from "axios";
import { getToken, formatToken } from "@/utils/auth";
import { ElMessage } from "element-plus";

const defaultConfig = {
  baseURL: '',
  // 请求超时时间
  timeout: 10000,
  headers: {
    Accept: "application/json, text/plain, */*",
    "Content-Type": "application/json",
    "X-Requested-With": "XMLHttpRequest"
  },
};
class PureHttp {
  constructor() {
    this.httpInterceptorsRequest();
    this.httpInterceptorsResponse();
  }
  /** 重连原始请求 */
  static retryOriginalRequest(config) {
    return new Promise(resolve => {
      PureHttp.requests.push((token) => {
        config.headers["Authorization"] = formatToken(token);
        resolve(config);
      });
    });
  }
  /** 请求拦截 */
  httpInterceptorsRequest() {
    PureHttp.axiosInstance.interceptors.request.use(async (config) => {
      // 优先判断post/get等方法是否传入回调，否则执行初始化设置等回调
      if (typeof config.beforeRequestCallback === "function") {
        config.beforeRequestCallback(config);
        return config;
      }
      if (PureHttp.initConfig.beforeRequestCallback) {
        PureHttp.initConfig.beforeRequestCallback(config);
        return config;
      }
      /** 请求白名单，放置一些不需要`token`的接口 */
      const whiteList = ["/refresh-token", "/login"];
      return whiteList.some(url => config.url.endsWith(url))
        ? config
        : new Promise(resolve => {
          const data = getToken();
          if (data) {
            const now = new Date().getTime();
            const expired = parseInt(data.expires) - now <= 0;
            if (expired) {
              if (!PureHttp.isRefreshing) {
                PureHttp.isRefreshing = true;
                // token过期刷新
                useUserStoreHook()
                  .handRefreshToken({ refreshToken: data.refreshToken })
                  .then(res => {
                    const token = res.data.accessToken;
                    config.headers["Authorization"] = formatToken(token);
                    PureHttp.requests.forEach(cb => cb(token));
                    PureHttp.requests = [];
                  })
                  .finally(() => {
                    PureHttp.isRefreshing = false;
                  });
              }
              resolve(PureHttp.retryOriginalRequest(config));
            }
            else {
              config.headers["Authorization"] = formatToken(data.accessToken);
              resolve(config);
            }
          }
          else {
            resolve(config);
          }
        });
    }, error => {
      return Promise.reject(error);
    });
  }
  /** 响应拦截 */
  httpInterceptorsResponse() {
    const instance = PureHttp.axiosInstance;
    instance.interceptors.response.use((response) => {
      const $config = response.config;
      // 优先判断post/get等方法是否传入回调，否则执行初始化设置等回调
      if (typeof $config.beforeResponseCallback === "function") {
        $config.beforeResponseCallback(response);
        return response.data;
      }
      if (PureHttp.initConfig.beforeResponseCallback) {
        PureHttp.initConfig.beforeResponseCallback(response);
        return response.data;
      }
      return response.data;
    }, (error) => {
      const { response } = error;
      let errorMessage = "";
      if (response.config.method === "get") {
        errorMessage = "获取数据失败！";
      } else {
        errorMessage = "操作失败！";
      }
      ElMessage({
        message: errorMessage,
        type: "warning"
      })
      const $error = error;
      $error.isCancelRequest = Axios.isCancel($error);
      // 所有的响应异常 区分来源为取消请求/非取消请求
      return Promise.reject($error);
    });
  }
  /** 通用请求工具函数 */
  request(method, url, param, axiosConfig) {
    const config = Object.assign(Object.assign({
      method,
      url
    }, param), axiosConfig);
    // 单独处理自定义请求/响应回调
    return new Promise((resolve, reject) => {
      PureHttp.axiosInstance
        .request(config)
        .then((response) => {
          resolve(response);
        })
        .catch(error => {
          reject(error);
        });
    });
  }
}
/** `token`过期后，暂存待执行的请求 */
PureHttp.requests = [];
/** 防止重复刷新`token` */
PureHttp.isRefreshing = false;
/** 初始化配置对象 */
PureHttp.initConfig = {};
/** 保存当前`Axios`实例对象 */
PureHttp.axiosInstance = Axios.create(defaultConfig);

export const http = new PureHttp();
